/**
 * @file thread_limit_probe_minimal.cpp
 * @brief 在 64 位 Linux 系统上探测最多能创建多少个线程，仅输出最终统计信息。
 *
 * 编译方式：
 *     g++ -std=c++17 -O2 -pthread thread_limit_probe_minimal.cpp -o thread_limit_probe_minimal
 *
 * 运行方式：
 *     ./thread_limit_probe_minimal
 *
 * 在程序运行过程中按 Ctrl+C 可提前停止创建线程，程序会输出最终统计并优雅退出。
 */

#include <atomic>
#include <chrono>
#include <csignal>
#include <exception>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <vector>

#include <sys/resource.h>
#include <unistd.h>

// -----------------------------------------------------------------------------
// 全局控制标志
// -----------------------------------------------------------------------------

/// 控制工作线程是否继续执行。
std::atomic<bool> g_keep_threads_running{true};

/// 控制主线程是否继续创建新线程。
std::atomic<bool> g_keep_creating_threads{true};

// -----------------------------------------------------------------------------
// 信号处理
// -----------------------------------------------------------------------------

/**
 * @brief SIGINT (Ctrl+C) 信号处理函数，通知主线程和工作线程结束。
 */
void handle_signal(int) {
    g_keep_creating_threads.store(false, std::memory_order_relaxed);
    g_keep_threads_running.store(false, std::memory_order_relaxed);
}

// -----------------------------------------------------------------------------
// 工具函数
// -----------------------------------------------------------------------------

/**
 * @brief 读取 /proc/self/status 中的 Threads、VmSize、VmRSS 信息。
 * @return 返回格式化后的字符串，如读取失败则返回提示信息。
 */
std::string read_proc_self_status_summary() {
    std::ifstream status("/proc/self/status");
    if (!status) {
        return "  无法读取 /proc/self/status\n";
    }

    std::string line;
    std::string output;
    while (std::getline(status, line)) {
        if (line.rfind("Threads:", 0) == 0 ||
            line.rfind("VmSize:", 0) == 0 ||
            line.rfind("VmRSS:", 0) == 0) {
            output += "  " + line + "\n";
        }
    }

    if (output.empty()) {
        output = "  /proc/self/status 中未找到目标字段\n";
    }
    return output;
}

/**
 * @brief 读取 RLIMIT_STACK 软限制，方便在统计中展示。
 * @return 以字节为单位的栈大小软限制，如无限制则返回 0。
 */
unsigned long get_stack_soft_limit_bytes() {
    struct rlimit limit {};
    if (getrlimit(RLIMIT_STACK, &limit) != 0) {
        return 0;
    }
    if (limit.rlim_cur == RLIM_INFINITY) {
        return 0;
    }
    return static_cast<unsigned long>(limit.rlim_cur);
}

// -----------------------------------------------------------------------------
// 工作线程函数
// -----------------------------------------------------------------------------

/**
 * @brief 工作线程主体——循环睡眠，直到收到退出通知。
 */
void worker_thread() {
    while (g_keep_threads_running.load(std::memory_order_relaxed)) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

// -----------------------------------------------------------------------------
// 主函数
// -----------------------------------------------------------------------------

int main() {
    std::cout << "线程创建探测程序启动 (PID " << getpid() << ")\n";

    // 安装 Ctrl+C 信号处理函数。
    std::signal(SIGINT, handle_signal);

    // 预先保留容量，减少向量扩容次数。
    std::vector<std::thread> threads;
    threads.reserve(1024);

    // 记录失败信息。
    bool creation_failed = false;
    std::string failure_reason = "用户主动中断";
    int failure_errno = 0;

    try {
        while (g_keep_creating_threads.load(std::memory_order_relaxed)) {
            threads.emplace_back(worker_thread);
        }
    } catch (const std::system_error& e) {
        creation_failed = true;
        failure_reason = e.what();
        failure_errno = e.code().value();
    } catch (const std::bad_alloc& e) {
        creation_failed = true;
        failure_reason = std::string("bad_alloc: ") + e.what();
    } catch (const std::exception& e) {
        creation_failed = true;
        failure_reason = std::string("异常: ") + e.what();
    }

    // 输出最终统计信息。
    std::cout << "\n==== 线程创建最终统计 ====\n";
    std::cout << "成功创建线程总数 : " << threads.size() << "\n";
    if (creation_failed) {
        std::cout << "终止原因           : 创建线程失败\n";
        std::cout << "错误信息           : " << failure_reason << "\n";
        if (failure_errno != 0) {
            std::cout << "错误码 (errno)     : " << failure_errno << "\n";
        }
    } else if (!g_keep_creating_threads.load(std::memory_order_relaxed)) {
        std::cout << "终止原因           : 用户发送 SIGINT\n";
    } else {
        std::cout << "终止原因           : 正常结束\n";
    }

    unsigned long stack_soft_limit = get_stack_soft_limit_bytes();
    if (stack_soft_limit > 0) {
        std::cout << "线程栈软限制 (字节) : " << stack_soft_limit << "\n";
    } else {
        std::cout << "线程栈软限制        : unlimited 或获取失败\n";
    }

    std::cout << "\n进程资源快照:\n" << read_proc_self_status_summary();
    std::cout << "===========================\n";

    // 通知所有工作线程退出循环。
    g_keep_threads_running.store(false, std::memory_order_relaxed);

    // 回收所有线程资源。
    for (auto& t : threads) {
        if (t.joinable()) {
            t.join();
        }
    }

    std::cout << "所有线程已回收，程序结束。\n";
    return 0;
}